﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using MonitorServer;
using MS.Internal.Mita.Foundation;
using MS.Internal.Mita.Foundation.Controls;
using MS.Internal.Mita.Foundation.Waiters;

namespace WordTestApp
{
    public static class StartWord
    {
        public static WindowOpenedWaiter wordWaiter = new WindowOpenedWaiter(UICondition.CreateFromClassName("OpusApp"));
        public static WindowOpenedWaiter wordWaiter2 = new WindowOpenedWaiter(UICondition.CreateFromClassName("OpusApp"));

        public static ControlsWriter wrt = new ControlsWriter();
        public static void Start(string fileFullName, string location)
        {
            WordMonitor monitor = new WordMonitor() { Location = location, FileName = fileFullName };
            wrt.Write("word Test", ConsoleColor.Red);
            //Start NotePad
            wrt.Write("Start word...", ConsoleColor.Red);
            #region Start word
            var startTime = DateTime.Now;
            System.Diagnostics.Process.Start("Winword");
            //Wait for NotePad to open
            wordWaiter.Wait();
            UIObject word = wordWaiter.Source;
            var endTime = DateTime.Now;
            DisplayView(startTime, endTime);
            monitor.StartTime = startTime;
            monitor.LoadAppTime = (endTime - startTime).TotalMilliseconds;
            #endregion

            #region Template
            wrt.Write("Template Test", ConsoleColor.Red);
            DSMTemplate template = new DSMTemplate();
            startTime = template.TemplateMenuClickLetter();
            int count = 0;
            while (false == Monitor.GetTopWindowText().ToLower().Contains("word"))
            {
                count++;
                Console.WriteLine("=======text={1}======={0}", Monitor.GetTopWindowText(), count);
                System.Threading.Thread.Sleep(1000);
                if (count > 100) break;
            }
            Console.WriteLine("=======text2========{0}", Monitor.GetTopWindowText());
            endTime = DateTime.Now;
            DisplayView(startTime, endTime);
            monitor.LoadTemplateTime = (endTime - startTime).TotalMilliseconds;
            #endregion

            #region Write Test
            System.Threading.Thread.Sleep(5000);

            wrt.Write("Write Test", ConsoleColor.Red);
            wordWaiter2.Wait();
            UIObject word2 = wordWaiter2.Source;

            startTime = DateTime.Now;
            try
            {
                var f = word2.Descendants.Find(UICondition.Create("@ClassName='_WwB'"));
            }
            catch
            {
            }

            Edit editBox = new Edit(word2.Descendants.Find(UICondition.Create("@ClassName='_WwB'")));
            Keyboard.Instance.SendKeysDelay = 30;
            editBox.SetFocus();
            //editBox.SendKeys("^a^x");
            editBox.SendKeys("This is a Performance Testing Demo provided by wicresoft..{Enter}");
            endTime = DateTime.Now;
            DisplayView(startTime, endTime);
            monitor.WriteTime = (endTime - startTime).TotalMilliseconds;
            #endregion

            #region Save
            wrt.Write("Save Test", ConsoleColor.Red);
            //Save
            Button saveMenuBtn = new Button(word2.Descendants.Find(UICondition.Create("@AccessKey='Alt, 1'")));
            saveMenuBtn.Click();

            //WindowOpenedWaiter saveWinWait = new WindowOpenedWaiter(UICondition.CreateFromClassName("#32770"));   //win7
            WindowOpenedWaiter saveWinWait = new WindowOpenedWaiter(UICondition.CreateFromClassName("bosa_sdm_msword"));   //XP
            saveWinWait.Wait();

            Window saveWin = new Window(saveWinWait.Source);
            //saveWin.SetFocus();

            //FileNameControlHost
            //Edit editSave = new Edit(saveWin.Descendants.Find("FileNameControlHost"));   //win7
            Edit editSave = new Edit(saveWin.Descendants.Find("54"));   //xp
            editSave.SetFocus();
            editSave.SendKeys("^a^x");
            editSave.SendKeys(fileFullName);
            startTime = DateTime.Now;

            editSave.SendKeys("{Enter}");

            count = 0;
            var fileName =Path.GetFileName(fileFullName).ToLower();
            while (false == Monitor.GetTopWindowText().ToLower().Contains(fileName))
            {
                count++;
                Console.WriteLine("=======save text={1}======={0}", Monitor.GetTopWindowText(), count);
                System.Threading.Thread.Sleep(1000);
                if (count > 300) break;
            }
            Console.WriteLine("=======save text======={0}", Monitor.GetTopWindowText());

            endTime = DateTime.Now;
            DisplayView(startTime, endTime);
            monitor.SaveTime = (endTime - startTime).TotalMilliseconds;
            #endregion

            #region Close
            wordWaiter2.Reset();
            word2 = wordWaiter2.Source;

            wrt.Write("Close Test", ConsoleColor.Red);

            //File menu
            try
            {
                var f = word2.Descendants.Find("FileTabButton");
            }
            catch
            {
            }
            MenuOpenedWaiter fileMenuWaiter = new MenuOpenedWaiter();

            Button FileMenuBtn = new Button(word2.Descendants.Find("FileTabButton"));
            FileMenuBtn.Click();
            fileMenuWaiter.Wait();
            Menu formatMenu = new Menu(fileMenuWaiter.Source);

            //System.Threading.Thread.Sleep(10000);
            try
            {
                var e = formatMenu.Descendants.Find(UICondition.Create("@AccessKey='Alt, F, X'"));
            }
            catch
            {
            }
            Button exitMenuBtn = new Button(formatMenu.Descendants.Find(UICondition.Create("@AccessKey='Alt, F, X'")));
            startTime = DateTime.Now;
            exitMenuBtn.Click();
            endTime = DateTime.Now;
            DisplayView(startTime, endTime);
            monitor.CloseTime = (endTime - startTime).TotalMilliseconds;
            monitor.EndTime = endTime;
            monitor.Insert();
            #endregion
        }

        private static void DisplayView(DateTime startTime, DateTime endtime)
        {
            wrt.Write(string.Format("    Start time:{0}", startTime.ToString("yyMMdd HH:mm:ss")), ConsoleColor.White);
            wrt.Write(string.Format("    End time:{0}", endtime.ToString("yyMMdd HH:mm:ss")), ConsoleColor.White);
            wrt.Write(string.Format("    Spend time:{0}ms", (endtime - startTime).TotalMilliseconds), ConsoleColor.White);
        }

        private static void ConsoleLog(UIObject obj)
        {
            foreach (var c in obj.Children)
            {
                Console.WriteLine("--c------------{0},{1},{2},{3}", c.ClassName, c.Name, c.RuntimeId, c.AccessKey);
            }

            foreach (var c in obj.Descendants)
            {
                Console.WriteLine("--D------------{0},{1},{2},{3}", c.ClassName, c.Name, c.RuntimeId, c.AccessKey);
            }
        }
    }
    class Monitor
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        static extern int GetWindowTextLength(IntPtr hWnd);

        //  int GetWindowText( 
        //      __in   HWND hWnd, 
        //      __out  LPTSTR lpString, 
        //      __in   int nMaxCount 
        //  ); 
        [DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        //  DWORD GetWindowThreadProcessId( 
        //      __in   HWND hWnd, 
        //      __out  LPDWORD lpdwProcessId 
        //  ); 
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        //HANDLE WINAPI OpenProcess( 
        //  __in  DWORD dwDesiredAccess, 
        //  __in  BOOL bInheritHandle, 
        //  __in  DWORD dwProcessId 
        //); 
        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr handle);

        //  DWORD WINAPI GetModuleBaseName( 
        //      __in      HANDLE hProcess, 
        //      __in_opt  HMODULE hModule, 
        //      __out     LPTSTR lpBaseName, 
        //      __in      DWORD nSize 
        //  ); 
        [DllImport("psapi.dll")]
        private static extern uint GetModuleBaseName(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        //  DWORD WINAPI GetModuleFileNameEx( 
        //      __in      HANDLE hProcess, 
        //      __in_opt  HMODULE hModule, 
        //      __out     LPTSTR lpFilename, 
        //      __in      DWORD nSize 
        //  ); 
        [DllImport("psapi.dll")]
        private static extern uint GetModuleFileNameEx(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        public static string GetTopWindowText()
        {
            IntPtr hWnd = GetForegroundWindow();
            int length = GetWindowTextLength(hWnd);
            StringBuilder text = new StringBuilder(length + 1);
            GetWindowText(hWnd, text, text.Capacity);

            return text.ToString();
        }

        public static string GetTopWindowName()
        {
            IntPtr hWnd = GetForegroundWindow();
            uint lpdwProcessId;
            GetWindowThreadProcessId(hWnd, out lpdwProcessId);

            IntPtr hProcess = OpenProcess(0x0410, false, lpdwProcessId);

            StringBuilder text = new StringBuilder(1000);
            //GetModuleBaseName(hProcess, IntPtr.Zero, text, text.Capacity); 
            GetModuleFileNameEx(hProcess, IntPtr.Zero, text, text.Capacity);
            CloseHandle(hProcess);

            return text.ToString();
        }
    }

}